import { INestApplication, ValidationPipe } from "@nestjs/common";
import { WINSTON_MODULE_NEST_PROVIDER } from "nest-winston";
import { getServerConfig } from "../ormconfig";
import helmet from "helmet";
import rateLimit from "express-rate-limit";
import { HttpExceptionFilter } from "@/filters/http-exception.filter";
import { TransformInterceptor } from "@/interceptors/transform.interceptor";
import * as express from "express";
import { logger } from "@/common/log4js/logger.middleware";
import { mw as requestIpMw } from "request-ip";
import { ExceptionsFilter } from "@/filters/exceptions-filter";
import { SwaggerModule, DocumentBuilder } from "@nestjs/swagger";
import { knife4jSetup } from "nestjs-knife4j";
import { isDev } from "@/config";

export const setupApp = (app: INestApplication) => {
    const config = getServerConfig();
    console.log("config", config);
    // 设置 api 访问前缀
    // app.setGlobalPrefix(config.API_PREFIX);
    // 获取真实 ip
    app.use(requestIpMw({ attributeName: "ip" }));
    // 日志
    app.use(express.json());  // 注意：除了错误级别的中间件，其他的中间件，必须在路由之前进行配置  通过 express.json() 这个中间件，解析表单中的 JSON 格式的数据
    app.use(express.urlencoded({ extended: true }));// 通过 express.urlencoded() 这个中间件，来解析表单中的 url-encoded 格式的数据
    app.use(logger);
    // 使用全局拦截器打印出参
    app.useGlobalInterceptors(new TransformInterceptor());
    // 所有异常
    // app.useGlobalFilters(new ExceptionsFilter());
    // app.useGlobalFilters(new HttpExceptionFilter());//全局http过滤器
    // 添加全局自动验证管道
    app.useGlobalPipes(
        new ValidationPipe({
            /** 负载对象自动转换 */
            transform: true,
            transformOptions: { enableImplicitConversion: true },
            /** 自动过滤未知参数 */
            whitelist: true
        })
    );
    
    // app.useGlobalGuards()
    // 弊端 -> 无法使用DI -> 无法访问userService
    
    // app.useGlobalInterceptors(new SerializeInterceptor());
    
    // helmet头部安全  开启导致 swagger不能通过内网访问
    // app.use(helmet());
    
    // rateLimit限流
    app.use(
        rateLimit({
            windowMs: 1 * 60 * 1000, // 1 minutes
            max: 300 // limit each IP to 100 requests per windowMs
        })
    );
    
    //初始化Swagger文档
    if(isDev){
        const swaggerOptions = new DocumentBuilder()
            .setTitle("网盘加速接口文档")
            .setDescription("接口文档")
            .setVersion("1.0.0")
            .addBearerAuth(
                {
                    type: "http",
                    scheme: "bearer",
                    bearerFormat: "JWT",
                    name: "Authorization",
                    description: "Enter your JWT token in this format - Bearer token",
                    in: "header"
                }
            )
            .build();
    
        const document = SwaggerModule.createDocument(app, swaggerOptions);
        // 项目依赖当前文档功能，最好不要改变当前地址
        // 生产环境使用 nginx 可以将当前文档地址 屏蔽外部访问
        SwaggerModule.setup(`api`, app, document);
        knife4jSetup(app, {
            urls: [
                {
                    name: "2.X版本",
                    url: `/api-json`,
                    swaggerVersion: "3.0",
                    location: `/api-json`
                }
            ]
        });
    }
    
};
